// Header Protection
#ifndef _VECTOR_H_
#define _VECTOR_H_

// Include Files
#include <Windows.h>
#include <xmmintrin.h>

// Namespace
namespace IE
{
	/////////////////////////////////////////////////////////////////////////////////
	// Type Definitions

	typedef __m128 vector_t;

	/////////////////////////////////////////////////////////////////////////////////
	// vector_t Declarations

	inline vector_t Vector()
	{
		return _mm_setzero_ps();
	}

	inline vector_t Vector( float_t _fX, float_t _fY, float_t _fZ, float_t _fW )
	{
		return _mm_set_ps(_fW, _fZ, _fY,_fX );
	}

	inline vector_t Vector( float_t _fV )
	{
		return _mm_set1_ps(_fV);
	}

	inline vector_t VectorSetX( vector_t _vYZW, float _fX )
	{
		// copy the vector, cast it as a flat array, and set the x value
		vector_t vRet = _vYZW;
		((float*)&vRet)[0] = _fX;
		return vRet;
	}

	inline vector_t VectorSetY( vector_t _vXZW, float_t _fY )
	{
		// copy the vector, cast it as a float array, and set the y value
		vector_t vRet = _vXZW;
		((float*)&vRet)[1] = _fY;
		return vRet;
	}

	inline vector_t VectorSetZ( vector_t _vXYW, float_t _fZ )
	{
		// copy the vector, cast it as a float array, and set the z value
		vector_t vRet = _vXYW;
		((float*)&vRet)[2] = _fZ;
		return vRet;
	}

	inline vector_t VectorSetW( vector_t _vXYZ, float_t _fW )
	{
		// copy the vector, cast it as a float array, and set the w value
		vector_t vRet = _vXYZ;
		((float*)&vRet)[3] = _fW;
		return vRet;
	}

	inline vector_t Vector( float_t const *_pfV )
	{
		return _mm_load_ps(_pfV);
	}

	inline vector_t VectorAdd( vector_t _lhs, vector_t _rhs )
	{
		return _mm_add_ps(_lhs, _rhs);
	}

	inline vector_t VectorSub( vector_t _lhs, vector_t _rhs )
	{
		return _mm_sub_ps(_lhs, _rhs);
	}

	inline vector_t VectorMul( vector_t _lhs, vector_t _rhs )
	{
		return _mm_mul_ps(_lhs, _rhs);
	}

	inline vector_t VectorDiv( vector_t _lhs, vector_t _rhs )
	{
		return _mm_div_ps(_lhs, _rhs);
	}

	// TODO: this may not need to reverse, check it out, also, move this somewhere
#define VEC_SHUFFLE_MASK(a, b, c, d) _MM_SHUFFLE(d, c, b, a)

	template< int iMask >
	inline vector_t VectorShuffle( vector_t _lhs, vector_t _rhs )
	{
		return _mm_shuffle_ps(_lhs, _rhs, iMask);
	}

	vector_t VectorDot( vector_t _lhs, vector_t _rhs );

	vector_t VectorCross( vector_t _lhs, vector_t _rhs );

	vector_t VectorNorm( vector_t _lhs );
}

// Header Protection
#endif // _VECTOR_H_
